#include "../../src/conexion.h"
#include "string.h"

static int recibir_conexion=0;
//0 es que nada paso
//1 es que se inicio la conexion del cliente
//2 es que se establecio la conexion del cliente
//3 es que se acepto la conexion en el server
//4 es que se pidio terminar la conexion


#define CLIENTE 222
#define SERVER 111
conexion *cliente;
conexion *servidor;

int conexion_conectar(conexion *c, char *servidor){
  recibir_conexion=1;
  c->socket=CLIENTE;//EL CLIENTE
  cliente=c;
  conexion_set_status(c, CON_CONECTANDO); 
}

int conexion_escuchar(conexion *c, int puerto){
  //lalala
  conexion_set_status(c, CON_ABIERTO); 
}

int conexion_aceptar(conexion *accept, conexion **nuevo_cliente, conexion_callback callback){
  if(recibir_conexion==2){
  conexion_crear(nuevo_cliente, callback);
  (*nuevo_cliente)->socket=SERVER;
  conexion_publish(*nuevo_cliente, CON_NUEVA_CONEXION, 0, 0); 
  conexion_set_status(*nuevo_cliente, CON_CONECTADO); 
  servidor = *nuevo_cliente;
  recibir_conexion=3;
  }
  else{
    *nuevo_cliente=0;
  }
}

int conexion_desconectar(conexion *c){
  conexion_set_status(c, CON_DESCONECTANDO); 
  recibir_conexion=4;
  conexion_set_status(c, CON_DESCONECTADO); 
}


int conexion_procesar_envios(conexion *origen){
  void *datos;
  int size;
  if(cola_hay_datos(origen->mensajes_salientes))
    procesar_paquete_saliente(&(origen->paquete_saliente), &(origen->mensajes_salientes));
  paquete_saliente_a_socket_preparar(&(origen->paquete_saliente), &datos, &size);
  if(size!=0){
    int e = conexion_write(origen, datos, size);
    paquete_saliente_a_socket_resultado(&(origen->paquete_saliente), e);
  }
}

int conexion_procesar_recepciones(conexion *c){
  void *datos;
  int size;
  paquete_entrante_que_pedir(&(c->paquete_entrante), &datos, &size);
  int e = conexion_read(c, datos, size);
  paquete_entrante_mas_datos(&(c->paquete_entrante), e);
  procesar_paquete_entrante(&(c->paquete_entrante), &(c->mensajes_entrantes));
}

int conexion_procesar_conexion(conexion *c){
  if(recibir_conexion==1){
    recibir_conexion=2;
    conexion_set_status(c, CON_CONECTADO); 
  }
}

#define min(x,y) (x)>(y)?(y):(x)
#define TAM_PRUEBA 2 
char entrada_server[TAM_PRUEBA];
int s_entrada_server=0;
char entrada_cliente[TAM_PRUEBA];
int s_entrada_cliente=0;

int conexion_write(conexion *origen, void *datos, int size){
  char *destino;
  int *s_destino;
  if(origen==cliente){
    destino=entrada_server;
    s_destino=&s_entrada_server;
  }else{
    destino=entrada_cliente;
    s_destino=&s_entrada_cliente;
  }
  if(*s_destino==0){
    int n = min(TAM_PRUEBA, size);
    memcpy(destino, datos, n);
    *s_destino=n;
    return n;
  }
  return 0;
}

int conexion_read(conexion *destino, void *datos, int size){
  char *origen;
  int *s_origen;
  if(destino==servidor){
    origen=entrada_server;
    s_origen=&s_entrada_server;
  }else{
    origen=entrada_cliente;
    s_origen=&s_entrada_cliente;
  }
  if(*s_origen==0 || size==0)
    return 0;
  if(*s_origen <= size){
    memcpy(datos, origen, *s_origen);
    int n=*s_origen;
    *s_origen=0;
    return n;
  }else{
    memcpy(datos, origen, size);
    memcpy(origen, origen+size, *s_origen-size);
    *s_origen-=size;
    return size;
  }
}


